package fr.n7.sma.view.model;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.event.EventListenerList;

import fr.n7.sma.util.FiniteSizeLinkedList;
import fr.n7.sma.view.listeners.AgentViewPropertiesListener;

public class AgentViewProperties {
	
	private Color color;
	private Color traceColor;
	private FiniteSizeLinkedList<TraceModel> traces;
	private Map<String, Icon> images;
	private Icon image;
	private Icon symbol;
	private JLabel label;
	private BufferedImage originalImage;
	
	private EventListenerList listeners = new EventListenerList();
	private int w;
	private int h;

	public AgentViewProperties(Color color, BufferedImage image) {
		super();
		this.label = new JLabel();
		this.color = color;
		this.traceColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 150);
		setOriginalImage(image);
		putOriginalImageIcon();
	}
	
	public AgentViewProperties(Color color, BufferedImage image,  int w, int h) {
		super();
		this.label = new JLabel();
		this.color = color;
		this.traceColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 150);
		setOriginalImage(image);
		putSymbolIcon(w, h);
	}

	public JLabel getLabel() {
		return label;
	}
	
	public void putSymbolIcon(int w, int h){
		if(symbol == null || this.w != w || this.h != h){
			this.w = w;
			this.h = h;
			BufferedImage im = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
			Graphics2D g2d = (Graphics2D) im.getGraphics();
			g2d.setColor(traceColor);
			g2d.fillOval(0, 0, w-1, h-1);
			g2d.setColor(Color.black);
			g2d.drawOval(0, 0, w-1, h-1);
			symbol = new ImageIcon(im);
		}
		label.setIcon(symbol);
		label.revalidate();
		notifyChanged();
	}
	
	public void putOriginalImageIcon(){
		if(originalImage == null){
			throw new Error("Original Image not initialized !");
		}else if(image == null){
			image = new ImageIcon(colorizeImage(originalImage));
		}
		label.setIcon(image);
		label.revalidate();
		notifyChanged();
	}
	
	public void putResourceImageIcon(String resource, BufferedImage resourceImage){
		if(originalImage == null){
			throw new Error("Original Image not initialized !");
		}
		if(images == null){
			images = new HashMap<String, Icon>();
		}
		Icon icon = images.get(resource);
		if(icon == null){
			int w = originalImage.getWidth();
			int h = originalImage.getHeight();
			BufferedImage im = colorizeImage(originalImage);
			Graphics2D g2d = (Graphics2D) im.getGraphics();
			g2d.drawImage(resourceImage, w/2, h/2, w, h, 0, 0, im.getWidth(), im.getHeight(), null);
			icon = new ImageIcon(im);
			images.put(resource, icon);
		}
		label.setIcon(icon);
		label.revalidate();
		notifyChanged();
	}

	public void setLabelVisible(boolean b){
		label.setVisible(b);
	}
	
	public FiniteSizeLinkedList<TraceModel> getTraces() {
		return traces;
	}

	public void setTraces(FiniteSizeLinkedList<TraceModel> traces) {
		this.traces = traces;
		notifyChanged();
	}

	public void setColor(Color color) {
		this.color = color;
		this.traceColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 150);

		if(images != null){
			images.clear();
		}
		symbol = null;
		image = null;
	}
	
	public Color getColor() {
		return color;
	}
	
	public void addListener(AgentViewPropertiesListener l){
		listeners.add(AgentViewPropertiesListener.class, l);
	}
	
	public void removeListener(AgentViewPropertiesListener l){
		listeners.remove(AgentViewPropertiesListener.class, l);
	}
	
	private void notifyChanged(){
		for(AgentViewPropertiesListener l : listeners.getListeners(AgentViewPropertiesListener.class)){
			l.agentViewPropertiesChanged();
		}
	}

	private BufferedImage colorizeImage(BufferedImage image){
		int w = image.getWidth();
		int h = image.getHeight();
		BufferedImage im = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
		Graphics2D g2d = (Graphics2D) im.getGraphics();
		g2d.drawImage(image, 0, 0, null);
		g2d.setComposite(AlphaComposite.DstIn);
		g2d.setColor(new Color(255, 255, 255, 250));
		g2d.fillRect(0, 0, w, h);
		g2d.setComposite(AlphaComposite.SrcAtop);
		g2d.setColor(traceColor);
		g2d.fillRect(0, 0, w, h);
		return im;
	}
	
	public void setOriginalImage(BufferedImage originalImage) {
		this.originalImage = originalImage;
		if(images != null){
			images.clear();
		}
		image = new ImageIcon(colorizeImage(originalImage));
	}

}
